package com.wujie.mall.domain.payment.impl;

import com.wujie.mall.domain.payment.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * 支付宝支付渠道实现
 * 
 * 设计模式应用：工厂方法模式的具体产品
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
@Component
public class AlipayChannel implements PaymentChannel {

    private static final String ALIPAY_GATEWAY = "https://openapi.alipay.com/gateway.do";
    
    @Override
    public PaymentResponse pay(PaymentRequest request) {
        log.info("开始处理支付宝支付，订单号: {}, 金额: {}", request.getOrderNo(), request.getAmount());
        
        try {
            // 验证请求参数
            validateRequest(request);
            
            // 模拟支付宝支付处理
            String paymentNo = generateAlipayTradeNo(request.getOrderNo());
            String paymentForm = buildAlipayForm(request, paymentNo);
            
            log.info("支付宝支付预处理成功，支付单号: {}", paymentNo);
            
            return PaymentResponse.success(request.getOrderNo(), paymentNo, paymentForm);
            
        } catch (Exception e) {
            log.error("支付宝支付处理失败，订单号: {}", request.getOrderNo(), e);
            return PaymentResponse.failure(request.getOrderNo(), "ALIPAY_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse queryPaymentStatus(String orderNo) {
        log.info("查询支付宝支付状态，订单号: {}", orderNo);
        
        try {
            // 模拟查询支付宝支付状态
            // 在实际应用中，这里会调用支付宝的查询接口
            Thread.sleep(100); // 模拟网络延迟
            
            // 模拟随机支付状态
            boolean isPaid = Math.random() > 0.3; // 70%概率支付成功
            
            if (isPaid) {
                String paymentNo = generateAlipayTradeNo(orderNo);
                PaymentResponse response = PaymentResponse.success(orderNo, paymentNo, null);
                response.putExtraData("trade_status", "TRADE_SUCCESS");
                response.putExtraData("gmt_payment", LocalDateTime.now().toString());
                return response;
            } else {
                return PaymentResponse.pending(orderNo, generateAlipayTradeNo(orderNo));
            }
            
        } catch (Exception e) {
            log.error("查询支付宝支付状态失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "QUERY_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentResponse cancelPayment(String orderNo) {
        log.info("取消支付宝支付，订单号: {}", orderNo);
        
        try {
            // 模拟取消支付宝支付
            Thread.sleep(50); // 模拟网络延迟
            
            PaymentResponse response = PaymentResponse.builder()
                    .success(true)
                    .status(PaymentResponse.PaymentStatus.CANCELLED)
                    .orderNo(orderNo)
                    .responseTime(LocalDateTime.now())
                    .build();
            
            response.putExtraData("cancel_time", LocalDateTime.now().toString());
            
            log.info("支付宝支付取消成功，订单号: {}", orderNo);
            return response;
            
        } catch (Exception e) {
            log.error("取消支付宝支付失败，订单号: {}", orderNo, e);
            return PaymentResponse.failure(orderNo, "CANCEL_ERROR", e.getMessage());
        }
    }

    @Override
    public PaymentType getPaymentType() {
        return PaymentType.ALIPAY;
    }

    /**
     * 生成支付宝交易号
     * @param orderNo 订单号
     * @return 支付宝交易号
     */
    private String generateAlipayTradeNo(String orderNo) {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return "ALIPAY_" + timestamp + "_" + uuid;
    }

    /**
     * 构建支付宝支付表单
     * @param request 支付请求
     * @param paymentNo 支付单号
     * @return 支付表单HTML
     */
    private String buildAlipayForm(PaymentRequest request, String paymentNo) {
        // 在实际应用中，这里会根据支付宝SDK构建真实的支付表单
        StringBuilder form = new StringBuilder();
        form.append("<form id='alipaysubmit' name='alipaysubmit' action='").append(ALIPAY_GATEWAY).append("' method='POST'>");
        form.append("<input type='hidden' name='service' value='create_direct_pay_by_user'/>");
        form.append("<input type='hidden' name='partner' value='2088000000000000'/>");
        form.append("<input type='hidden' name='out_trade_no' value='").append(request.getOrderNo()).append("'/>");
        form.append("<input type='hidden' name='subject' value='").append(request.getSubject()).append("'/>");
        form.append("<input type='hidden' name='body' value='").append(request.getBody()).append("'/>");
        form.append("<input type='hidden' name='total_fee' value='").append(request.getAmount()).append("'/>");
        form.append("<input type='hidden' name='notify_url' value='").append(request.getNotifyUrl()).append("'/>");
        form.append("<input type='hidden' name='return_url' value='").append(request.getReturnUrl()).append("'/>");
        form.append("<input type='hidden' name='_input_charset' value='utf-8'/>");
        form.append("<input type='submit' value='立即支付' style='display:none;'/>");
        form.append("</form>");
        form.append("<script>document.forms['alipaysubmit'].submit();</script>");
        
        return form.toString();
    }

    @Override
    public void validateRequest(PaymentRequest request) {
        PaymentChannel.super.validateRequest(request);
        
        // 支付宝特有的验证逻辑
        if (request.getSubject() == null || request.getSubject().trim().isEmpty()) {
            throw new IllegalArgumentException("支付宝支付必须提供商品名称");
        }
        
        if (request.getNotifyUrl() == null || request.getNotifyUrl().trim().isEmpty()) {
            throw new IllegalArgumentException("支付宝支付必须提供异步通知地址");
        }
        
        // 支付宝金额限制：单笔最小0.01元，最大50万元
        if (request.getAmount().compareTo(new java.math.BigDecimal("0.01")) < 0) {
            throw new IllegalArgumentException("支付宝支付金额不能小于0.01元");
        }
        
        if (request.getAmount().compareTo(new java.math.BigDecimal("500000")) > 0) {
            throw new IllegalArgumentException("支付宝支付金额不能超过50万元");
        }
        
        log.debug("支付宝支付请求验证通过，订单号: {}", request.getOrderNo());
    }
}